home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gekkan Dennou Club 147
/
Gekkan Dennou Club - 2000.8 Vol. 147 (Japan).7z
/
Gekkan Dennou Club - 2000.8 Vol. 147 (Japan) (Track 1).bin
/
tools
/
ask
/
askdates
/
source
/
askdates.s
< prev
next >
Wrap
Text File
|
1998-08-24
|
30KB
|
1,220 lines
******************************************************************************
* ASK3アクセサリ ASKDates V2.01
* Copyright 1998 by AIG-Soft
******************************************************************************
.include defines.mac
.include pspdef.mac
.include ask3.mac
.cpu 68000
******************************************************************************
* 常駐ルーチン
******************************************************************************
* 1998をわざわざテキストでなしにバイナリー化しているのは、テキストのみより
* 誤った一致をしにくいから
.text
.even
KEEP_START:
* 常駐確認用識別子
id: .dc.b 'ASKDates V2.01',19,98,'AIG-Soft',0
******************************************************************************
* ワーク1
******************************************************************************
* このワークエリアは起動時に初期値が必要/初期化時に利用するものである。
*
.even
ACh .dc.l -1 * アクセサリアドレス(初期値-1<0)
* 正常登録された時、ACh>=0になる(0,1,2,3...)
Ffmt0 .dc.l 0 * フォーマットワーク(全部)
Ffmt .dc.l 0 * フォーマットワーク(フォーマット部分のみ)
Ffmte .dc.l 0 * フォーマットワーク最終アドレス+1
Dfmt .dc.l 0 * 現在参照中のフォーマット
all .dc.l 0 * ワークエリアサイズ
first .dc.b $ff * No=$00/Yes=$ff
fhigh .dc.b $ff * 高位メモリー確保(=0:No,!=0:Yes)
.even
******************************************************************************
* メッセージ
******************************************************************************
MesNichiji .dc.b '日時選択',0
.even
******************************************************************************
* フォーマット指定子
******************************************************************************
* 置換対象文字列は$ffxxで示される
* $ffは漢字2バイト目に来ない
.if 0
YR4 equ $ff01 * 西暦4桁
YR2 equ $ff02 * 西暦下2桁
GN2 equ $ff03 * 平成2桁
MON equ $ff04 * 月2桁
DAY equ $ff05 * 日2桁
WKE equ $ff06 * 曜日英字3桁
WKJ equ $ff07 * 曜日日本語1桁
H24 equ $ff08 * 24時制時間
H12 equ $ff09 * 12時制時間
APM equ $ff0a * AM/PM
MIN equ $ff0b * 分
SEC equ $ff0c * 秒
.endif
******************************************************************************
StoreFMT:
* 指定フォーマットで文字列をストアする
* d0.b <- フォーマット置換番号(1~)
* a2.l <- バッファー
* -> a2.l
* d0/d1/d2/a1破壊
movem.l d4-d5,-(sp)
move.w week(opc),d4
move.w hh(opc),d5
moveq.l #0,d1
move.b d0,d1 * .b = .w
add.w d1,d1
move.w Ftable-2(pc,d1.w),d0 * 番号は1からだから-2しておく
jsr Ftable(pc,d0.w)
movem.l (sp)+,d4-d5
rts
*
Ftable:
.dc.w Jfmt01-Ftable * 西暦4桁
.dc.w Jfmt02-Ftable * 西暦下2桁
.dc.w Jfmt03-Ftable * 平成2桁
.dc.w Jfmt04-Ftable * 月2桁
.dc.w Jfmt05-Ftable * 日2桁
.dc.w Jfmt06-Ftable * 曜日英字3桁
.dc.w Jfmt07-Ftable * 曜日日本語1桁
.dc.w Jfmt08-Ftable * 24時制時間
.dc.w Jfmt09-Ftable * 12時制時間
.dc.w Jfmt0a-Ftable * AM/PM
.dc.w Jfmt0b-Ftable * 分
.dc.w Jfmt0c-Ftable * 秒
*
* YYYY/MM/DD
* 0123456789
Jfmt02: * 西暦下2桁
lea workd+2(pc),a1
bra dt2
Jfmt04: * 月2桁
lea workd+5(pc),a1
bra dt2
Jfmt05: * 日2桁
lea workd+8(pc),a1
dt2: moveq.l #2-1,d2 * size (-1 for dbra)
bra dt
Jfmt01: * 西暦4桁
lea workd(pc),a1
moveq.l #4-1,d2 * size
dt: move.b (a1)+,(a2)+
dbra d2,dt
rts
Jfmt07: * 曜日日本語1桁
add.w d4,d4 * for .w
lea Jyoubi(pc,d4.w),a1
bra dt2
Jfmt06: * 曜日英字3桁
move.w d4,d0
add.w d4,d4 * *2
add.w d0,d4 * = *3
lea Eyoubi(pc,d4.w),a1
moveq.l #3-1,d2 * (-1 for dbra)
bra dt
Jfmt03: * 平成2桁
* 1989年=平成元年 ; 1980年+9年
move.w heisei(opc),d5
Store10: * ここはサブルーチンでもある
* d5.w = 数字10進2桁まで
and.l #$0000_ffff,d5 * .w = .l
divu #10,d5 * d5.l/10 = d5.l.w ... d5.h.w
bsr @f * d5/10
swap d5 * d5%10
@@: add.b #'0',d5
move.b d5,(a2)+
rts
** 届くようにここに置く
.even
Jyoubi .dc.b '日月火水木金土'
Eyoubi .dc.b 'SUNMONTUEWEDTHUFRISAT'
.even
**
* HH:MM:SS
* 01234567
Jfmt08: * 24時制時間
lea workt(pc),a1
bra dt2
Jfmt0b: * 分
lea workt+3(pc),a1
bra dt2
Jfmt0c: * 秒
lea workt+6(pc),a1
bra dt2
Jfmt09: * 12時制時間
tst.w d5
bne @f
* hh==0 : 12時制では00時は存在しない->12時
moveq.l #12,d5
bra Store10
*
@@: cmp.w #13,d5 * hh<13?
bcs Store10
sub.w #12,d5 * hh-=12
bra Store10
Jfmt0a: * AM/PM
moveq.l #'P',d0
cmp.w #12,d5 * hh>=12?
bcc @f * Yes
moveq.l #'A',d0
@@: move.b d0,(a2)+
move.b #'M',(a2)+
rts
******************************************************************************
MakeDT:
* フォーマット種類に応じた文字列を作成する
move.l Dfmt(pc),a0 * フォーマット
lea cbuf(opc),a2
@@: move.b (a0)+,d0
cmp.b #$ff,d0
bne 1f
* 置換対象文字列 d0.b->(a2)+
move.b (a0)+,d0
bsr StoreFMT * a1破壊
bra @b
*
1: * 通常文字
move.b d0,(a2)+
bne @b * EOSまで
rts
******************************************************************************
ZNumStr:
* 数字を全角文字列化してストア
* 入力:d3.w= y=1~9999(4桁まで)
* a2 = buf
* 出力:a2 = 次のbuf位置
* 破壊:d0-d2/a0
moveq.l #0,d0 * for .w = .l (divuのため)
move.w d3,d0
*
moveq.l #1,d1 * 桁数
cmp.w #10,d0
bcs @f * <10
moveq.l #2,d1 * 桁数
cmp.w #100,d0
bcs @f * <100
moveq.l #3,d1 * 桁数
cmp.w #1000,d0
bcs @f * <1000
moveq.l #4,d1 * 桁数(>=1000)
@@: move.w d1,d2
add.w d2,d2 * 桁数*2
lea (a2,d2.w),a0
move.l a0,d2 * push a0
subq.l #1,d1 * -1 for dbra
@@: divu #10,d0 * d0.l/10 = d0.l.w ... d0.h.w
swap d0
add.b #$4f,d0
move.b d0,-(a0) * d0%10
move.b #$82,-(a0)
clr.w d0 * 余りを消す for d0=d0/10
swap d0
dbra d1,@b
move.l d2,a2
rts
******************************************************************************
CnvNen:
* int CnvNen(unchar *nen,unchar *buf)
* 4 8
* 年号変換
* nen(cbuf) -> buf
* return : 0=変換不可 , 1=変換可能
* YYYY(西暦) → 元号YY
* 元号略号YY → YYYY(西暦)
regs = 4*2
movem.l d3/d4,-(sp)
movem.l 4+regs(sp),a1/a2 * a1=nen,a2=buf
*
moveq.l #0,d3 * y=0
*
move.b (a1)+,d0
lsl.w #8,d0
move.b (a1)+,d0 * 最初の1文字(全角)
cmp.w #'a',d0
bcs @f * <'a'
cmp.w #'z',d0
bhi @f * >'z'
sub.w #'a'-'A',d0 * 全角英小文字->大文字化
*
@@: moveq.l #-1,d4
lea ryaku(pc),a0 * 元号略号か?
@@: addq.w #1,d4 * i
move.w (a0)+,d1
beq 1f * End of table
cmp.w d1,d0
bne @b
* 元号略号が有った
bra LNEN * 元号の後ろの数字取得へ
*
1: * 元号略号無し
* 正式元号チェック;全角2文字
swap d0 * d0<<16
move.b (a1),d0
lsl.w #8,d0
move.b 1(a1),d0 * 次の1文字(全角)
*
moveq.l #-1,d4
lea gens(pc),a0 * 元号略号か?
@@: addq.w #1,d4 * i
move.l (a0)+,d1
beq 12f * End of table
cmp.l d1,d0
bne @b
* 正式元号が有った
addq.l #2,a1 * 次の1文字も飛ばす
bra LNEN * 元号の後ろの数字取得へ
*
12: swap d0 * 最初の1文字へ戻す
11: * 年の取得
cmp.w #'0',d0
bcs @f * <'0'
cmp.w #'9',d0
bhi @f * >'9'
* 0~9
add.w d3,d3 * y*2
move.w d3,d1
add.w d3,d3 * y*4
add.w d3,d3 * y*8
add.w d1,d3 * y*8+y*2=y*10
sub.w #'0',d0
add.w d0,d3
*
LNEN: move.b (a1)+,d0
lsl.w #8,d0
move.b (a1)+,d0 * 最初の1文字(全角)
bra 11b
*
@@: tst.w d3
ble ret0 * y<=0
cmp.w #9999,d3
bls @f
* y>9999
ret0: moveq.l #0,d0 * 変換不可;年がない/年がおかしい
bra oret
*
@@: * 変換
cmp.w #GEN,d4 * 元号か?
beq 1f * No
* 元号->西暦;有り得ない元号年でも計算可能
add.w d4,d4 * for .w
move.w nens(pc,d4.w),d0 * nens[i]
subq.w #1,d0 * y+=(nens[i]-1); // 元年=1年だから-1
add.w d0,d3
bra 2f
*
1: * 西暦->元号
moveq.l #0,d4 * i
move.l d4,d2 * i for nen[]
10: move.w nens(pc,d2.w),d0 * nens[i]
addq.w #2,d2
move.w nens(pc,d2.w),d1 * nens[i+1]
cmp.w d0,d3
bcs 3f * y<nens[i]
cmp.w d1,d3
bcc 3f * y>=nens[i+1]
* 範囲内
subq.w #1,d0 * nens[i]-1
sub.w d0,d3 * y-=..
move.l d4,d2
add.w d2,d2 * 2
add.w d2,d2 * 4
lea gens(pc,d2.w),a0
moveq.l #4-1,d0
@@: move.b (a0)+,(a2)+ * 元号文字列コピー
dbra d0,@b
bra 2f
*
3: addq.w #1,d4 * i++
cmp.w #GEN,d4
bne 10b
bra ret0
*
2: * 年(全角)
bsr ZNumStr * d3.w,a2
* 年の後コピー
subq.l #2,a1 * nen-2
@@: move.b (a1)+,(a2)+
bne @b
*
moveq.l #1,d0 * 変換可能
oret: movem.l (sp)+,d3/d4
rts
*
* 西暦 元号 元号略号
* 1868~1912 明治 1~45 M
* 1912~1926 大正 1~15 T
* 1926~1989 昭和 1~64 S
* 1989~ 平成 1~ H
*
* 届くようにここに置く(全部even始まり)
ryaku .dc.w 'M','T','S','H',0
gens .dc.b '明治大正昭和平成',0,0,0,0 * 最後の04つは0.l
nens .dc.w 1868,1912,1926,1989,9999
GEN equ 4 * 元号の種類数(nensは1つ多い)
.even
******************************************************************************
GetDate macro
* -> heisei
* -> week
* -> workd = YYYY/MM/DD
* 0123456789
IOCS _DATEGET
move.l d0,d1
IOCS _DATEBIN * d0.l = WY.YY.MM.DD ; YY=1980~2079,W=0;日~6;土
move.l d0,d1
and.l #$0fff_ffff,d1 * DATEASC=YYYY/MM/DD
move.l d0,d2
swap d2 * dtb>>16 : WY.YY
and.w #$0fff,d2 * YYY
sub.w #1988,d2 * heisei=(dtb>>16)&0xfff-1989+1; // 平成年;元年=1年
move.w d2,heisei
rol.l #4,d0 * 上位から下位へ4ビット回転で移動
and.w #$000f,d0 * W
move.w d0,week
lea workd(opc),a1
IOCS _DATEASC * d1.l=MD.YYYY/MM/DD -> (a1)+
.endm
*-----------------------------------------------------
GetTime macro
* -> hhのみ
* -> workt = HH:MM:SS
* 01234567
local L1
IOCS _TIMEGET
move.l d0,d1
IOCS _TIMEBIN * 00.HH.MM.SS
move.l d0,d1
swap d0
move.w d0,hh * HHのみ
lea workt(opc),a1
IOCS _TIMEASC * HH:MM:SS -> (a1)+
lea workt(opc),a1
move.b (a1),d0
cmp.b #' ',d0 * HH<10のとき、その10の位が' 'になるので'0'にする
bne L1
move.b #'0',(a1) * ' ' -> '0'
L1: *
.endm
*-----------------------------------------------------
Dates:
* short Dates(BIT16K code)
* 日付・時刻入力/年号変換 アクセサリ本体
* 入力:4+2(sp) = BIT16K キーコード
* 出力:d0.w = リターンコード
move.w 4+2(sp),d2 * BIT16K キーコード
move.w #CACI_NORMAL,d7 * ret=規定外キー入力の時のため
*
move.w #-1,-(sp) * read BREAK mode
DOS _BREAKCK
move.w d0,brksts
clr.w -(sp) * BREAK Cut
DOS _BREAKCK
addq.w #2*2,sp * BREAKOFF
*
tst.b first * first?
beq 2f * -> No
tst.b cbuf * cbuf[0]=0?
beq 2f * -> Yes
* 変換ラインに入力がある = 年号変換
pea zbuf(opc)
pea cbuf(opc)
bsr CnvNen
addq.l #8,sp
tst.l d0
bne @f
* 変換不可
clr.b cbuf * cbuf[0]=0; こうしないとcbufは勝手に消えてくれない
moveq.l #7,d1
IOCS _B_PUTC * BEEP
move.w #CACI_END,d7 * エラー時は無効
bra 10f
*
@@: move.w #CR,d2 * 以下CRで処理
*
2: * 変換ラインへの入力はない = 日付・時刻入力
* キーを探して各ルーチンへ飛ぶ
lea Jtable(pc),a0
move.w d2,d1
and.w #NAKEY,d1
@@: move.l (a0)+,d0 * jump|code
beq 10f * -> end of table
cmp.w d1,d0 * =code?
bne @b * no
swap d0 * d0=jump
jsr -4(a0,d0.w)
*
10: move.w brksts(opc),-(sp) * BREAKON
DOS _BREAKCK
addq.w #2,sp
*
moveq.l #0,d0 * for .w = .l
move.w d7,d0
rts
*---------------------------------------
Jtable: * 各キー毎のジャンプテーブル(出てきやすい順に並べる)
* jump先(offset),code
* OPT.1+記号入力 : 起動/終了
* ↑↓ : 選択
* CR : 決定&終了
* SPC : 半角決定&終了
* ESC : 終了
.dc.w Jup-$,NOT_ASCII|UP_KEY
.dc.w Jdown-$,NOT_ASCII|DOWN_KEY
.dc.w Jcr-$,CR
.dc.w Jspc-$,SPC
.dc.w Jesc-$,ESC
.dc.w Jkigou-$,NOT_ASCII|KIGOU_KEY
.dc.w 0,0 * end of table
*---------------------------------------
Jkigou: * 起動
* btst.l #B_OPT1_ON,d2 * btstは.b/.lしかないため
btst.l #B_CTRL_ON,d2 * btstは.b/.lしかないため
beq 1f * CTRLが押されていない
tst.b first * first?
bne @f * -> Yes
* 2回目以降はキャンセルして終了
Jesc: * 終了
st.b first
move.w #CACI_END,d7 * 終了
1: rts
*
@@ clr.b first * first=0
* 日時読みだし(最初だけ)
GetDate * 日付読みだし -> workd,heisei,week
GetTime * 時刻読みだし -> workt,hh
lea MesNichiji(pc),a0
move.l #mbuf,d0
bsr Str2MEANS
move.w #DF_KWINSTR|DF_MWINSTR|CACI_NORMAL,d7
bra DEX2
*---------------------------------------
Jup: * ↑: 前のフォーマットへ
move.l Dfmt(pc),a0
cmp.l Ffmt(pc),a0
bne @f
move.l Ffmte(pc),a0 * 先頭である->最後へ
@@: subq.l #2,a0 * 前の$00の前
@@: tst.b (a0)
beq @f
subq.l #1,a0
bra @b
*
@@: addq.l #1,a0 * $00の次
bra DEX
*
Jdown: * ↓: 次のフォーマットへ
move.l Dfmt(pc),a0
@@: tst.b (a0)
beq @f
addq.l #1,a0
bra @b
*
@@: addq.l #1,a0 * $00の次
cmp.l Ffmte(pc),a0
bne DEX
move.l Ffmt(pc),a0 * 最後である->先頭へ
DEX: move.l a0,Dfmt
move.w #DF_KWINSTR|CACI_NORMAL,d7
DEX2: * 変換ラインに全角化して表示
bsr MakeDT
pea zbuf(opc)
pea cbuf(opc)
pea 13.w * 半角→全角
DOS _KNJCTRL
lea 12(sp),sp
*
lea zbuf(opc),a0
move.l #kbuf,d0
Str2MEANS: * ここはサブルーチンでもある
* buf[Str2MEAN(mes,buf,1)]=0
* a0 <- mes
* d0.l <- buf
pea 1.w * 今回は反転表示しかない
move.l d0,-(sp) * buf
pea (a0) * mes
pea 62.w
DOS _KNJCTRL
lea 4*4(sp),sp
move.l -8(sp),a0 * buf
add.w d0,d0 * .w=MEAN
clr.w (a0,d0.w) * buf[..]=0
*
rts
*---------------------------------------
Jcr: * 全角出力
lea zbuf(pc),a0
lea cbuf(pc),a1
@@: move.b (a0)+,(a1)+ * strcpy(cbuf,zbuf)
bne @b
Jspc: * 半角出力
move.w #DF_OUTSTR|CACI_END,d7
st.b first
rts
******************************************************************************
* ワーク2
******************************************************************************
* ここに置くワークは、常駐後に使われるもの
* これらのワークエリアは常駐後に利用可能になるので、
* 以下の非常駐ルーチンからは参照しないこと
*--------------------------------------------------------------------
* オフセットテーブルの定義
.offset 0
*--------------------------------------------------------------------
_brksts .ds.w 1 * BREAKフラグ
_kbuf .ds.w K_SIZE * 変換ラインへ
_mbuf .ds.w M_SIZE * モード表示領域へ
_cbuf .ds.b C_SIZE * 仮入力行 -> 入力行へ(ユーザーの入力へ)
_zbuf .ds.b C_SIZE * 全角化文字列格納エリア
_heisei .ds.w 1
_week .ds.w 1
_hh .ds.w 1
_workd .ds.b 11 * 日付文字列格納エリア
_workt .ds.b 9 * 時刻文字列格納エリア
.even
_keep_end .ds.w 0 * オフセットのみ
*--------------------------------------------------------------------
* 実際のワークエリアの定義
*--------------------------------------------------------------------
.text * .offset解除
work2:
brksts equ work2+_brksts
kbuf equ work2+_kbuf
mbuf equ work2+_mbuf
cbuf equ work2+_cbuf
zbuf equ work2+_zbuf
heisei equ work2+_heisei
week equ work2+_week
hh equ work2+_hh
workd equ work2+_workd
workt equ work2+_workt
*********************************************************************
* ワークエリア転送ルーチン
*********************************************************************
* ワークエリアを低位メモリーに取るとき、mallocではなく常駐メモリーを多く取って
* プログラムの後ろに付ける。これは、メモリーの分断を防ぐためである。
*
TrnsWork:
* /hがないとき+常駐終了時のみここにくる
* a0,a2<- 元のFfmt0
* a1 <- KEEP_END
* d0.l <- ワークエリアサイズ
* d1.l <- 常駐サイズ
* d7.l <- exit code
* 転送
@@: move.b (a0)+,(a1)+ * 元Ffmt0->KEEP_END
dbra d0,@b
* 高位メモリーワーク解放
pea (a2) * Ffmt0
DOS _MFREE
addq.w #4,sp * めんどうなのでエラー処理は省略
ComEnd: * コマンドライン
clr.w -(sp) * exit(0)相当
move.l d6,-(sp) * 常駐サイズ
DOS _KEEPPR
TrnsWorkEnd:
*--------------------------------------------------------------------
* 転送ルーチンサイズ<ワークエリアサイズである
* 常駐部分最後
KEEP_END equ work2+_keep_end
******************************************************************************
* 非常駐ルーチン
******************************************************************************
* アクセサリ定義構造体
******************************************************************************
.even
ACdef:
.dc.w KS_EDIT0|KS_EDITING|KS_SELECT * いつでも
* .dc.w NOT_ASCII|OPT1_ON|KIGOU_KEY * 呼びだしキー
.dc.w NOT_ASCII|CTRL_ON|KIGOU_KEY * 呼びだしキー
.dc.l Dates * アクセサリーメイン
.dc.l cbuf
.dc.l kbuf
.dc.l mbuf
******************************************************************************
* アクセサリ 組み込み/解除/初期化
*******************************************************************************
DeleteAcc:
* 入力:a2 = ACh
* 出力:d0.l = 0:ok , !=0:エラー
* 破壊:d0
move.l a0,-(sp) * push a0
lea MesDates(pc),a0
bsr Print
move.l (a2),-(sp) * ACh
pea 61.w
DOS _KNJCTRL
addq.l #4*2,sp
lea MesDeleteOk(pc),a0 * ok message
tst.l d0
beq @f * ret=0:Ok
lea ErrCantDelete(pc),a0 * error
@@: bsr Print
move.l (sp)+,a0 * pop a0
rts
*******************************************************************************
AttachAcc:
* アクセサリの登録
* 入力:なし
* 出力:d0.l = 0:ok , !=0:エラー
* 破壊:d0,d1,a0
* ASKのバージョンチェック
pea 50.w
DOS _KNJCTRL
addq.l #4,sp
cmp.l #300,d0 * <300? (V3.00未満?)
bcc @f * No (V3.00以降)
* ASK V3.00以降でない
lea ErrASK3(pc),a0
moveq.l #3,d0 * return(3)
bra 1f
*
@@: * アクセサリの登録
lea MesDates(pc),a0
bsr Print
pea ACdef(pc)
pea 60.w
DOS _KNJCTRL
addq.l #4*2,sp
cmp.l #-1,d0 * error?
bne @f * no
* アクセサリに登録出来ない
lea ErrCantAttach(pc),a0
moveq.l #4,d0 * return(4)
bra 1f
*
@@: move.l d0,ACh * ACh=ret;
lea MesAttachOk(pc),a0
moveq.l #0,d0 * return(0)
1: bsr Print
rts
******************************************************************************
SetFormats:
* フォーマットファイルの読み込み
movem.l d1-d3/d6/a0-a2,-(sp)
clr.w -(sp)
pea fname(opc)
DOS _OPEN
addq.l #6,sp
move.l d0,d6
bpl @f
moveq.l #1,d0 * ファイルが見つからない
bra Ret0
*
@@: move.w #2,-(sp)
clr.l -(sp)
move.w d6,-(sp)
DOS _SEEK * ファイルサイズ
move.l d0,all
move.l d0,d2 * len
clr.w -(sp)
clr.l -(sp)
move.w d6,-(sp)
DOS _SEEK * ファイル先頭へ戻す
lea 16(sp),sp
*
* ファイルを読むこむためのワーク確保
move.l d2,-(sp) * len
move.w #2,-(sp) * 常に上位メモリーから
DOS _MALLOC2
addq.l #6,sp
tst.l d0
bgt @f
moveq.l #2,d3 * メモリー確保出来ない
bra Ret2
*
@@: move.l d0,Ffmt0
move.l d0,a0
*
* フォーマットファイルはまるごと読み込めば良い
move.l d2,-(sp) * len
move.l a0,-(sp) * Ffmt0
move.w d6,-(sp) * fp
DOS _READ
lea 10(sp),sp
cmp.l d2,d0
beq @f
moveq.l #3,d3 * READ error
bra Ret
*
@@: * ワーク設定
lea HEADLEN(a0),a1
move.l a1,Ffmt
move.l a1,Dfmt * 最初
add.l a0,d2 * Ffmt0+len
move.l d2,Ffmte * ワークエンド+1
*
* ヘッダーチェック
moveq.l #0,d3 * ret=0
moveq.l #HEADLEN-1,d0
* a0=Ffmt0
lea HEADER(pc),a2
@@: cmp.b (a0)+,(a2)+
dbne d0,@b
beq @f
moveq.l #4,d3 * ret=4 : ヘッダーが違う
@@: clr.b -1(a1) * Ffmt[-1]=0 : 前フォーマットサーチを止めるため
Ret: tst.l d3
beq Ret2
* エラー時 : Ffmt0解放
move.l Ffmt0(pc),d0
move.l d0,-(sp)
DOS _MFREE
addq.l #4,sp
Ret2: move.w d6,-(sp)
DOS _CLOSE
addq.w #2,sp
move.l d3,d0
Ret0: movem.l (sp)+,d1-d3/d6/a0-a2
rts
******************************************************************************
EPrint:
* エラー出力に表示する
* 表示は全てこれで行っている
* 入力:a0 = 文字列
* 破壊:なし
move.l d0,-(sp) * push d0
move.w #2,-(sp) * STDERR
pea (a0) * 文字列
DOS _FPUTS * エラー出力へ
addq.l #2+4,sp
move.l (sp)+,d0 * pop d0
rts
Print:
* 標準出力に表示する(リダイレクト可)
* 入力:a0 = 文字列
* 破壊:なし
move.l d0,-(sp) * push d0
pea (a0) * 文字列
DOS _PRINT
addq.l #4,sp
move.l (sp)+,d0 * pop d0
rts
******************************************************************************
* この中ではa0/a2は壊さないこと(プロセス管理ポインタ/コマンドラインを参照するため)
AMAX equ 10 * 最大引数数
* コマンドライン
* a2
* 0(a2) = コマンドライン長
* 1(a2)~ = コマンドライン
* '-r ',0 スペース/タブはそのまま
*
GetArgv:
* コマンドラインを解析して各要素の先頭アドレスをargvに、個数をargcに格納する
* 引数:a2 = コマンドライン
* 出力:d0.w = 引数数(=argc)
* 破壊:d0-d1
movem.l a2/a6,-(sp)
moveq.l #0,d1 * 引数数
tst.b (a2)+ * コマンドライン長を飛ばす
beq 2f * コマンドライン長=0 -> 引数なし
lea argv(pc),a6
@@: * SPC/TAB skip
move.b (a2)+,d0
beq 2f * コマンドライン終わり
cmp.b #SPC,d0 * skip SPC
beq @b
cmp.b #TAB,d0 * skip TAB
beq @b
* SPC/TAB以外の文字が有った
subq.l #1,a2
move.l a2,(a6)+ * argv記録
addq.w #1,d1 * 引数+1
cmp.w #AMAX,d1 * 最大数を越える?
bcc 2f * -> 越える
1: * 次のEOS/SPC/TABまで飛ばす
move.b (a2)+,d0
beq 2f * コマンドライン終わり
cmp.b #SPC,d0 * skip SPC
beq @b
cmp.b #TAB,d0 * skip TAB
bne 1b
bra @b
*
2: move.w d1,argc * 記録
move.w d1,d0
movem.l (sp)+,a2/a6
rts
*---------------------------------------------
CheckOption:
* コマンドラインから指定オプションを探す
* 必ずGetArgvを呼び出した後に使うこと
* オプション名は先頭1文字だけで判別
* 引数:d2.b = オプション名(英小文字1文字)
* 出力:d0.l = 0:なし , !=0:そのオプションの次のアドレス
* 破壊:d0-d1
movem.l a5-a6,-(sp)
move.w argc(pc),d1
beq 1f * 引数はない
subq.w #1,d1 * -1 for dbra
lea argv(pc),a6
@@: move.l (a6)+,a5 * argv[i]
move.b (a5)+,d0 * argv[i][0]
* オプションの1文字目は'/''-'
cmp.b #'/',d0
beq 2f
cmp.b #'-',d0
beq 2f
3: dbra d1,@b * 次へ
1: * (指定)オプションはない
moveq.l #0,d0
bra 4f
2: * '/''-'があった
move.b (a5)+,d0 * 次の1文字
or.b #$20,d0 * 英小文字化
cmp.b d2,d0 * 一致?
bne 3b * -> 不一致
move.l a5,d0 * オプション名の次のアドレス(!=0)
4: movem.l (sp)+,a5-a6
rts
*---------------------------------------------
Getfname:
* コマンドラインからオプション以外の指定番目の引数を取り出す
* 必ずGetArgvを呼び出した後に使うこと
* 引数:d2.w = 何番目か(1~argc)
* d0.l = 転送先アドレス(サイズ判定していないので十分なサイズを持つこと)
* 出力:d0.w = 0:なし , >=1:その引数番目
* 破壊:d0-d1
movem.l d3/a0/a5/a6,-(sp)
move.l d0,a0 * 転送先アドレス
move.w argc(pc),d1
beq 1f * argc=0:元から引数はない
cmp.w d1,d2 * argc>=指定番目?
bhi 1f * No : この番目の引数は絶対にない
subq.w #1,d1 * -1 for dbra
moveq.l #0,d3 * 順番
lea argv(pc),a6
2: move.l (a6)+,a5 * argv[i]
move.b (a5),d0 * argv[i][0]
cmp.b #'/',d0 * オプションは飛ばす
beq 3f
cmp.b #'-',d0
beq 3f
* 引数有り
addq.w #1,d3 * 引数順番
cmp.w d2,d3 * 指定順番のものか?
bne 3f * No
* 指定順番のものである -> 指定バッファーに転送
@@: move.b (a5)+,d0
beq 4f * EOS
cmp.b #SPC,d0 * 転送終了はEOS/SPC/TABがくるまで
beq 4f
cmp.b #TAB,d0
beq 4f
move.b d0,(a0)+
bra @b
*
4: clr.b (a0) * EOS
move.w d3,d0 * 引数有り
bra @f
*
3: dbra d1,2b * 次の引数へ
1: * 指定番目の引数はない
moveq.l #0,d0
move.b d0,(a0) * 転送先バッファーにもEOSだけ書き込んでおく
@@: movem.l (sp)+,d3/a0/a5/a6
rts
******************************************************************************
* メイン
******************************************************************************
.xref keepchk
main:
lea.l initsp(pc),sp * PROGRAM=の時のため
* タイトル表示
move.w #2,-(sp) * STDERR
pea title(pc) * 文字列
DOS _FPUTS * エラー出力へ
addq.l #2+4,sp
*
move.l #(id-KEEP_START),-(sp) * 識別子の相対位置
pea.l (a0) * 自分のメモリ管理ポインタ
bsr keepchk * 常駐チェック
addq.l #4*2,sp
move.b d0,d7 * d7 :0=常駐してない , -1=常駐している
* 引数チェック1
bsr GetArgv * argc/argv設定
tst.w d0
beq usage * 引数がない -> 説明表示 ; ASKDates V2は引数が必要
moveq.l #'r',d2 * -r : 常駐解除?
bsr CheckOption
tst.l d0
beq keep * no
*
* 常駐解除
*
tst.b d7 * 常駐している?
beq Err_NoKp * No -> error
* a0=常駐しているルーチンのメモリ管理ポインタ
* メモリー管理ポインタを飛ばし、ユーザープログラム先頭へ
* さらに、AChまで飛ばす
lea fhigh-KEEP_START+PSPSIZ(a0),a4 * fhighのアドレス
tst.b (a4) * ワークは高位メモリー?
beq @f * No : 低位メモリーの時は解放ずみ
lea Ffmt0-KEEP_START+PSPSIZ(a0),a2
move.l (a2),-(sp) * Ffmt0のアドレス
DOS _MFREE * メモリー解放
addq.w #4,sp
@@: lea.l ACh-KEEP_START+PSPSIZ(a0),a2 * AChのアドレス
bsr DeleteAcc * アクセサリ解除
tst.l d0
bne Err_Kai * アクセサリ登録削除不可により常駐解除不可
*
pea.l MPSIZ(a0)
DOS _MFREE * 自己プロセスメモリー解放
addq.l #4,sp
tst.l d0
bmi Err_Kai * なぜかメモリー解放出来ない時
*
* 常駐解除正常終了
lea MesRelease(pc),a0
bsr Print
clr.w -(sp) * exit(0)
DOS _EXIT2
keep: * 常駐
tst.b d7 * 常駐している?
bne Err_Dbl * Yes -> error(2重常駐)
*
* プログラム起動時にはフリーエリアの全てが起動プログラムに割り当てられているため、
* これを必要部分以外解放する。そうしないとMALLOCが効かない。
* a0=プログラムメモリ管理ポインタ
* a1=プログラム終了アドレス+1(.data,.bssを含む)
lea MPSIZ(a0),a0 * メモリー管理ポインタ分を飛ばす
move.l a0,ProcAD * このプロセスの先頭アドレス保存
sub.l a0,a1 * 当プログラムサイズ
move.l a1,-(sp) * 確保する領域サイズ
move.l a0,-(sp) * 確保する領域の先頭アドレス
DOS _SETBLOCK * 空き領域確保
addq.w #4*2,sp
tst.l d0
bmi Err_Mem * 領域が確保できない時=エラー
*
* フォーマットファイル名取得
lea fname(opc),a3 * .bssなので(pc)は使えない
moveq.l #1,d2 * 1番目
move.l a3,d0 * fname
bsr Getfname
tst.w d0
beq Err_NoFmt * フォーマットファイルが指定されていない
*
* フォーマットファイル読み込み
bsr SetFormats
tst.l d0
bne Err_Fmt * フォーマットエラー
*
* アクセサリ組み込み
bsr AttachAcc
tst.l d0
bne Err_Keep * 組み込みエラー
*
* アクセサリも組み込みOK
lea MesKeep(pc),a0
bsr Print
move.l #KEEP_END-KEEP_START,d6 * 基本常駐サイズ
moveq.l #'h',d2 * -h : 高位メモリー?
bsr CheckOption
tst.l d0
bne ComEnd * Yes
*
* 低位メモリーの時
clr.b fhigh * 低位メモリー確保の印
*
* ワークエリアアドレス変更
* このプロセスの占めるメモリー領域を拡大してワークも入るようにする
add.l all(pc),d6 * ワークエリアサイズ
move.l d6,d0
add.l #PSPSIZ-MPSIZ,d0 * プロセス管理ポインタ分も含める
move.l d0,-(sp) * new size
move.l ProcAD(pc),-(sp)
DOS _SETBLOCK
addq.w #8,sp
bmi Err_Mem * メモリー不足
*
* TrnsWorkを小さくするために、できるだけこちらに置いている
* ワークエリアポインターを変更
move.l Ffmt0(pc),a2 * 元のFfmt0
lea KEEP_END(pc),a1
move.l a1,Ffmt0 * Ffmt0をKEEP_ENDに変更
*
move.l Ffmt(pc),d0
sub.l a2,d0
add.l a1,d0
move.l d0,Ffmt
move.l d0,Dfmt
*
move.l Ffmte(pc),d0
sub.l a2,d0
add.l a1,d0
move.l d0,Ffmte
*
lea KEEP_END(pc),a1 * (a0) -> (a1)
move.l a2,a0 * a0=a2=元のFfmt0
move.l all(pc),d0 * サイズ
subq.l #1,d0 * -1 for dbra
bra TrnsWork
*
* エラー終了
*
Err_Mem: * メモリーが不足している
lea.l ErrCantGetWrk(pc),a0
bra error
Err_Fmt: * フォーマットファイルが異常
lea.l ErrFmt(pc),a0
bra.s error
Err_NoFmt: * フォーマットファイルが指定されていない
lea.l ErrNoFmt(pc),a0
bra.s error
Err_NoKp: * 常駐していないのに解除しようとした
lea.l NoKeep(pc),a0
bra.s error
Err_Dbl: * 2重常駐
lea.l AlreadyKeep(pc),a0
bra.s error
Err_Keep: * 常駐できない
lea.l CantKeep(pc),a0
bra.s error
Err_Kai: * 常駐解除不可
lea.l CantRelease(pc),a0
bra.s error
usage: * 使用法
lea.l MesUsage(pc),a0
error: bsr EPrint * エラー出力へ表示
erRet: move.w #2,-(sp) * exit(2)
DOS _EXIT2
******************************************************************************
* メッセージなど
******************************************************************************
.even
MesDates: .dc.b 'アクセサリ「日付・時刻入力/年号変換」',0
MesDeleteOk: .dc.b 'を削除しました',$0d,$0a,0
ErrCantDelete: .dc.b 'が削除できません',$0d,$0a,0
ErrCantAttach: .dc.b 'が登録できません',$0d,$0a,0
MesAttachOk: .dc.b 'を登録しました',$0d,$0a,0
ErrASK3: .dc.b 'ASKがバージョン3以上ではありません',$0d,$0a,0
title: .dc.b 'ASK3アクセサリ ASKDates V2.01',$0d,$0a
.dc.b $09,'Copyright 1998 by AIG-Soft' * CrLfにつながる
CrLf .dc.b $0d,$0a
Eoss .dc.b 0
MesKeep: .dc.b '常駐しました',$0d,$0a,0
MesRelease: .dc.b '常駐解除しました',$0d,$0a,0
NoKeep: .dc.b '常駐していません',$0d,$0a,0
AlreadyKeep: .dc.b 'すでに常駐しています',$0d,$0a,0
CantKeep: .dc.b '常駐できません',$0d,$0a,0
CantRelease: .dc.b '常駐解除できません',$0d,$0a,0
MesUsage: .dc.b 'ASKDates フォーマットファイル [/R /H]',$0d,$0a,0
* メッセージ
ErrCantGetWrk: .dc.b 'ワークエリアが確保できません',$0d,$0a,0
ErrNoFmt .dc.b 'フォーマットファイルを指定して下さい',$0d,$0a,0
ErrFmt .dc.b 'フォーマットファイルが異常です',$0d,$0a,0
* フォーマットファイルヘッダー
HEADER .dc.b 'ASKDates FMT1',$0d,$0a,$1a
* 1234567890123 4 5 6
HEADLEN equ 16
.even
argc .ds.w 1 * 引数の個数
argv .ds.l AMAX * 各引数の先頭アドレス
******************************************************************************
* 非常駐ルーチンが使うワーク
******************************************************************************
.bss
.even
ProcAD .ds.l 1 * このプロセスの先頭アドレス
fname .ds.b 255 * 一時的にファイル名を格納するところ
******************************************************************************
* 非常駐ルーチンが使うスタック
******************************************************************************
.stack
.even
.ds.l 512
initsp:
******************************************************************************
.end main